
/* libc */
#include <stdio.h>

/* altera */
#include "bsp/system.h"
//#include "drivers/inc/altera_avalon_timer_regs.h"
//#include "sys/alt_irq.h"

/* ptp */
#include "hal/interval_timer_hal.h"
//#include "hcpp/ptp2_task_queue.h"

/* milisecond * (second * minute * hour * day) = day */
#define DAY_FACTOR      (1000 * 60 * 60 * 24)
#define SECOND_FACTOR   (1000)

static void interval_timer_hal_isr(void *context);

static volatile uint32_t day            = 0;
static volatile uint32_t day_fraction   = 0;
static volatile uint32_t sec            = 0;
static volatile uint32_t sec_fraction   = 0;
static volatile uint32_t msec           = 0;

static void
interval_timer_hal_isr(void *context);

/* lwip timer function */
uint32_t
sys_now(void)
{
    return msec;
}

/**
 * @brief   interval timer init
 *
 * @return  returns true if everything did well, false otherwise
 */
bool
interval_timer_hal_init(void)
{
    day             = 0;
    day_fraction    = 0;
    sec             = 0;
    sec_fraction    = 0;
    msec            = 0;
    sec             = msec / 1000;
    sec_fraction    = msec - (sec * 1000);
    
    /* start timer and enable timer interrupt */
//??    IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, ALTERA_AVALON_TIMER_CONTROL_START_MSK | ALTERA_AVALON_TIMER_CONTROL_ITO_MSK);
    
    /* register isr return code: "0" on success, failure otherwise */
//    if (alt_ic_isr_register(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ, interval_timer_hal_isr, NULL, 0)) {
//        return false;
//    }
    
    return true;
}

/**
 * @brief   interrupt service routine
 *
 * @param   context     not used
 */
static void
interval_timer_hal_isr(void *context)
{
    
    /* clear IRQ */
//    IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE, 0);
    
    /* see system.h: TIMER_0_PERIOD and TIMER_0_PERIOD_UNITS */
    msec         += TIMER_0_PERIOD;
    sec_fraction += TIMER_0_PERIOD;
    day_fraction += TIMER_0_PERIOD;
    if (day_fraction >= DAY_FACTOR) {
        day          += 1;
        day_fraction -= DAY_FACTOR;
    }
    
    if (sec_fraction >= SECOND_FACTOR) {
        sec          += 1;
        sec_fraction -= SECOND_FACTOR;
    }
    
    /* tell queue the current time */
//    ptp2_task_queue_tick(PTP2_TASK_QUEUE(), msec);
}

uint32_t
interval_timer_hal_get_milliseconds(void)
{
    return msec;
}

uint32_t
interval_timer_hal_get_seconds(void)
{
    return sec;
}

uint32_t
interval_timer_hal_get_second_fraction(void)
{
    return sec_fraction;
}

uint32_t
interval_timer_hal_get_days(void)
{
    return day;
}

